package com.ayf.payment.game.api.controller.paychannel;

import com.alibaba.fastjson.JSONObject;
import com.ayf.payment.game.api.channel.jiabei.util.JbStringUtil;
import com.ayf.payment.game.api.entity.Order;
import com.ayf.payment.game.api.type.OrderStatus;
import com.ayf.payment.game.api.utils.HttpServletRequestUtil;
import com.ayf.payment.game.api.utils.Md5Utils;
import com.ayf.payment.game.api.utils.SnowFlakeUtils;
import com.ayf.payment.game.api.wx.WxSendMsgUtils;
import com.swwx.charm.commons.lang.utils.LogPortal;
import com.swwx.charm.zookeeper.exception.GetLockFailedException;
import com.swwx.charm.zookeeper.exception.ReleaseLockFailedException;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * 优卡支付
 * @author wwl
 * @description:
 * @date 2020/5/13 20:13
 */
@RequestMapping("/v/yk/pay")
@RestController
public class YKPayNotifyController extends BasePayNotifyController {
    @Autowired
    private WxSendMsgUtils wxSendMsgUtils;
    @RequestMapping("/notify")
    public void notify(HttpServletRequest request, HttpServletResponse response) {
        String orderid = JbStringUtil.formatString(request.getParameter("orderid"));  //商户订单号
        super.notifyAsync(request,response,orderid);
    }

    @RequestMapping("/returns")
    public void returns(HttpServletRequest request, HttpServletResponse response) {
        String orderid = JbStringUtil.formatString(request.getParameter("orderid"));        //订单号
        super.notifySync(request,response,orderid);
    }

    @RequestMapping("/agentpay/notify")
    public void agentPayNotify(HttpServletRequest request, HttpServletResponse response) {
        String orderNo = JbStringUtil.formatString(request.getParameter("orderid"));        //订单号
        super.agentPayNotifyAsync(request,response,orderNo);
    }

    @Override
    protected void notifyAsyncBusinesExec(HttpServletRequest request, HttpServletResponse response,Object obj) {
        PrintWriter pw = null;
        String traceId = SnowFlakeUtils.getTraceId();
        try {
            pw = response.getWriter();
            //获取参数
            String orderid = JbStringUtil.formatString(request.getParameter("orderid"));  //商户订单号
            String opstate = JbStringUtil.formatString(request.getParameter("opstate"));  //订单结果
            String ovalue = JbStringUtil.formatString(request.getParameter("ovalue"));  //订单实际支付金额，单位元
            String sign = JbStringUtil.formatString(request.getParameter("sign"));   //32位小写MD5签名值，GB2312编码
            String sysorderid = JbStringUtil.formatString(request.getParameter("sysorderid"));  //此次订单过程中接口系统内的订单Id
            String msg = JbStringUtil.formatString(request.getParameter("msg"));    //订单结果说明
            LogPortal.info("{} 优卡交易异步通知 参数：orderid[{}] opstate[{}] ovalue[{}] sign[{}] sysorderid[{}] msg[{}]", traceId, orderid, opstate, ovalue,sign,sysorderid,msg);
            if (StringUtils.isEmpty(orderid)) {
                LogPortal.error("{} 优卡交易异步通知 商户订单号数值为空，不进行后续操作", traceId);
                pw.write("opstate=-1");
                pw.flush();
                return;
            }
            if (StringUtils.isEmpty(opstate)) {
                LogPortal.error("{} 优卡交易异步通知 订单结果为空，不进行后续操作", traceId);
                pw.write("opstate=-1");
                pw.flush();
                return;
            }
            Order order = orderService.selectByMerchantOrderNo(orderid);
            if (order == null) {
                LogPortal.error("{} 优卡交易异步通知 订单号[{}]在我方系统查询不到", traceId, orderid);
                pw.write("opstate=-1");
                pw.flush();
                return;
            }
            String KeyValue = systemInitialization.channelMap().get(order.getPayChannleId()).getChannelKey();
            StringBuffer dicStr=new StringBuffer();
            dicStr.append("orderid=").append(orderid);
            dicStr.append("&opstate=").append(opstate);
            dicStr.append("&ovalue=").append(ovalue);
            dicStr.append(KeyValue);
            String signVer = Md5Utils.md5(dicStr.toString());
            signVer = signVer.toLowerCase();
            if (sign.equals(signVer)) {
                OrderStatus orderStatus;
                if ("0".equals(opstate)){
                    orderStatus = OrderStatus.SUCCESS;
                } else{
                    orderStatus = OrderStatus.FAIL;
                    order.setScriptStatus(-1);
                }
                if (!OrderStatus.SUCCESS.equals(order.getOrderStatus())) {
                    String XY_GAME_PAY_LOCK_FLAG= System.getenv("XY_GAME_PAY_LOCK_FLAG");
                    String orderLockName = "orderLock".concat(this.getClass().getSimpleName()).concat(XY_GAME_PAY_LOCK_FLAG).concat(orderid);
                    boolean orderLock=false;
                    try {
                        if (orderLock = distributedLock.getLock(orderLockName)) {
                            Order order2 = orderService.selectByMerchantOrderNo(orderid);
                            if (order2 != null && OrderStatus.PROCESSING.equals(order2.getOrderStatus())){
                                order.setOrderNo(sysorderid);
                                order.setOrderStatus(orderStatus);
                                orderService.paymentOrder(order, new JSONObject());
                                if (OrderStatus.SUCCESS.equals(order.getOrderStatus())) {
                                    orderService.orderToGetWay(order);
                                    try {
                                        wxSendMsgUtils.rechargeSuccess(order);
                                    } catch (Exception e) {
                                        LogPortal.error("{} 优卡交易异步通知 商户订单号[{}]CallBack 微信通知异常", e, traceId, orderid);
                                    }
                                }
                            }
                        }
                    } catch (GetLockFailedException e) {
                        LogPortal.error("{} >>> [DISTRIBUTED_LOCK_ACQUIRE_FAILED_ZK] 分布式锁获取失败,锁名称为:{}", orderid, orderLockName);
                        LogPortal.error("{} >>> {} 获取lock失败", e, orderid, orderLockName);
                    } catch (Exception e) {
                        LogPortal.error("{} >>> {} 任务执行出错 ", e, orderid, orderLockName);
                    } finally {
                        if (orderLock) {
                            LogPortal.info(orderid + " >>> " + orderLockName + " finished.");
                            try {
                                distributedLock.releaseLock(orderLockName);
                            } catch (ReleaseLockFailedException e) {
                                LogPortal.error("{} >>> [DISTRIBUTED_LOCK_RELEASE_FAILED_ZK] 分布式锁释放失败,锁名称为:{}",orderid, orderLockName);
                                LogPortal.error("{} >>> {} 释放失败", e, orderid, orderLockName);
                            }
                        }
                    }
                }else{
                    LogPortal.info("{} 优卡交易异步通知 商户订单号[{}] 异步通知 不在更新订单状态：[{}]", traceId, orderid,order.getOrderStatus());
                }
                pw.write("opstate=0");
                pw.flush();
            }else{
                LogPortal.error("{} 优卡交易异步通知 商户订单号[{}] 验签失败", traceId, orderid);
                pw.write("opstate=-2");
                pw.flush();
            }
        }catch (Exception e){
            LogPortal.error("{} 优卡交易异步通知 验签业务逻辑处理失败，具体原因:{}", e, traceId, e.getMessage());
            pw.write("opstate=-1");
            pw.flush();
        }finally {
            if (pw != null)
                pw.close();
        }
    }

    @Override
    protected void notifySyncBusinesExec(HttpServletRequest request, HttpServletResponse response) {
        String orderno = JbStringUtil.formatString(request.getParameter("orderid"));
        try {
            String attach = JbStringUtil.formatString(request.getParameter("attach"));
            response.sendRedirect(attach + "/gws/loading.html?orderNo=" + orderno);
        } catch (Exception e) {
            LogPortal.error("订单号:{} 优卡交易同步通知 发生{}异常",e,orderno,e.getClass().getName());
        }
    }

    @Override
    protected void agentPayNotifyAsyncBusinesExec(HttpServletRequest request, HttpServletResponse response, Object obj) {
        String merchantOrderNo = JbStringUtil.formatString(request.getParameter("orderid"));
        String traceId = SnowFlakeUtils.getTraceId();
        LogPortal.info("{} 优卡代付异步通知 请求参数:{}",traceId,HttpServletRequestUtil.getRequestParameters(request));
        PrintWriter pw = null;
        try {
            String status = JbStringUtil.formatString(request.getParameter("opstate"));
            String amount = JbStringUtil.formatString(request.getParameter("ovalue"));
            String sign = JbStringUtil.formatString(request.getParameter("sign"));
            pw = response.getWriter();
            if (StringUtils.isBlank(sign)) {
                LogPortal.error("{} 订单号:{} 优卡代付异步通知失败，签名数值为空",traceId,merchantOrderNo);
                pw.write("opstate=-1");
                pw.flush();
                return;
            }
            if (StringUtils.isEmpty(merchantOrderNo)) {
                LogPortal.error("{} 优卡代付异步通知失败，代付订单号数值为空",traceId,merchantOrderNo);
                pw.write("opstate=-1");
                pw.flush();
                return;
            }
            if (merchantOrderNo.startsWith("Y")) {
                merchantCashOutService.YouKaPaymentOnBehalfOf(traceId,status,merchantOrderNo,sign,amount);
            } else {
                merchantPayOrderService.YouKaPayNotify(traceId,status,merchantOrderNo,sign,amount);
            }
            pw.write("opstate=0");
            pw.flush();
        } catch (Exception e) {
            LogPortal.error("{} 代付订单号:{} 优卡代付异步通知失败，业务处理失败，发生{}异常",e,traceId,merchantOrderNo,e.getClass().getName());
            pw.write("优卡代付异步通知业务处理失败：" + e.getMessage());
            pw.flush();
        } finally {
            if (pw != null)
                pw.close();
        }
    }
}
